-
Notifications
You must be signed in to change notification settings - Fork 930
Add experimentalForceOwningTab
for Web Worker support
#2197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
4ede337
to
f0287d4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM but I left a few nits and I think we need to refine when force can override canActAsPrimary...
* Whether to force enable persistence for the client. This cannot be used | ||
* with `synchronizeTabs:true` and is primarily intended for use with Web | ||
* Workers. Setting this to 'true' will enable persistence, but cause other | ||
* tabs using persistence to fail. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
note: If/when we ship this for real we should add more detail about exactly how other tabs will fail (so that developers can potentially write code to detect it, etc.).
if (indexedDB !== undefined) { | ||
request = indexedDB.open(name, version); | ||
} else { | ||
request = window.indexedDB.open(name, version); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since window
is usually the global object and we've already checked for the indexedDB
global directly, is there a case where we will ever hit this?
Maybe we have a fake window
object in node tests or something? Do you know?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I demand answers too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looked into this some more and since window
is bound to globalThis
in the dom, we won't ever hit this line unless window
has been mocked out and the indexedDB
global doesn't exist.
Deleted.
// If IndexedDb is available directly (ex: in case of web workers). | ||
if (typeof indexedDB !== 'undefined') { | ||
return true; | ||
} | ||
if (typeof window === 'undefined' || window.indexedDB == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per above, since window
is usually the global object and we've already checked for the indexedDB global directly, is there a case where we will ever hit this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We still need this for cases where indexedDB
and window
aren't available and return false, or else an environment without a global indexedDB that passes the other checks will incorrectly return true for isAvailable()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we just need to register the IndexedDb shim directly on globalAny
in node_persistence.ts
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added comment for why it's already registered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't that mean that "if (typeof window === 'undefined' || window.indexedDB == null)" is now no longer needed? Is your distinction from your first response here still relevant? if so, we should probably talk this through offline.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per offline conversation, removed the window logic, and flipped the indexedDB check to return false. By returning true automatically when IndexedDB is available, we are skipping all of the UA checks.
Also removed the window.navigator
check, to make sure workers aren't rejected early.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good for the purpose of gathering feedback!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for sticking through with me on this :)
return withPersistence('clientA', async db => { | ||
await withForcedPersistence('clientB', async () => { | ||
return expect( | ||
db.runTransaction('tx', 'readwrite-primary', () => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@@ -1005,11 +1024,12 @@ export class IndexedDbPersistence implements Persistence { | |||
|
|||
private detachWindowUnloadHook(): void { | |||
if (this.windowUnloadHandler) { | |||
assert(this.window != null, "'window' should be defined"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realized we've separated out asserts. thanks
@@ -239,7 +242,8 @@ export class IndexedDbPersistence implements Persistence { | |||
lruParams: LruParams, | |||
private readonly queue: AsyncQueue, | |||
serializer: JsonProtoSerializer, | |||
private readonly sequenceNumberSyncer: SequenceNumberSyncer | |||
private readonly sequenceNumberSyncer: SequenceNumberSyncer, | |||
private readonly forceOwningTab: boolean |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
@@ -587,6 +602,9 @@ export class IndexedDbPersistence implements Persistence { | |||
} | |||
|
|||
if (!this.isLocalClient(currentPrimary)) { | |||
if (this.forceOwningTab) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are already using the forceOwningTab
logic in updateClientMetadataAndTryBecomePrimary
, we don't need the check here anymore. Removed.
// If IndexedDb is available directly (ex: in case of web workers). | ||
if (typeof indexedDB !== 'undefined') { | ||
return true; | ||
} | ||
if (typeof window === 'undefined' || window.indexedDB == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per offline conversation, removed the window logic, and flipped the indexedDB check to return false. By returning true automatically when IndexedDB is available, we are skipping all of the UA checks.
Also removed the window.navigator
check, to make sure workers aren't rejected early.
'IndexedDB persistence is only available on platforms that support LocalStorage.' | ||
); | ||
this.webStorage = null; | ||
if (forceOwningTab === false) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now throw an error if synchronizeTabs
is used with experimentalForceOwningTab
, and we throw an error if LocalStorage is unavailable in WebStorageSharedClientState. Which case are we not covering?
…lientMetadataAndTryBecomePrimaryc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@@ -585,6 +585,9 @@ export class IndexedDbPersistence implements Persistence { | |||
private canActAsPrimary( | |||
txn: PersistenceTransaction | |||
): PersistencePromise<boolean> { | |||
if (this.forceOwningTab) { | |||
return PersistencePromise.resolve<boolean>(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably drop the generic since it can be inferred.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why TS can't infer it, but the error I get is:
Type 'PersistencePromise<true>' is not assignable to type 'PersistencePromise<boolean>'.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All language in index.d.ts LGTM with a tiny nit. Thanks!
packages/firebase/index.d.ts
Outdated
/** | ||
* Whether to force enable persistence for the client. This cannot be used | ||
* with `synchronizeTabs:true` and is primarily intended for use with Web | ||
* Workers. Setting this to 'true' will enable persistence, but cause other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was the intention to use backticks around true
? That would work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done.
config/functions/project.json
Outdated
@@ -0,0 +1,9 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean to commit this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for catching
Original issue: #983
Provides an experimental feature to support offline persistence in web workers.
I've updated the sample app with the latest changes as well (link).
There also seem to be some changes from running prettier that probably weren't pushed in other commits.